#!/bin/python
import argparse
import sys
import os
import shutil
from src.utils.runcmd import get_os_arch
from src.utils.getpkg import get_all_pkg
from src.core.global_config import GlobalConfig
from src.replace_vendor import ReplaceVendor
from src.rpm_build import RPMBuild
from src.rebuild_iso import RebuildISO
from src.utils import runcmd
from src.rebuild_iso_with_package import RebuildISOWithPackage
from src.utils.logger import logger


def init_config(parser):
    arch = get_os_arch()
    if not arch:
        sys.exit(1)
    GlobalConfig.ARCH = arch
    if parser.sub_cmd == "edvendor":
        get_edvendor_parser(parser)
    elif parser.sub_cmd == "ediso":
        get_ediso_parser(parser)
    elif parser.sub_cmd == "edreplace":
        get_edreplace_parser(parser)


def check_exist_tmpfile():
    tmpl_path = os.path.abspath(GlobalConfig.TMPL)
    if GlobalConfig.TMPL != "":
        if os.path.exists(tmpl_path) is False \
                or os.path.isdir(tmpl_path) is True:
            logger.error("tmpl file is not exists! path is %s",
                         GlobalConfig.TMPL)
            sys.exit(0)


def check_exist_outdir():
    if GlobalConfig.OUTPUT.endswith("iso") is False:
        logger.error("please define the --output like /xxx/xxx/xxx.iso")
        sys.exit(0)
    dirname = os.path.dirname(os.path.abspath(GlobalConfig.OUTPUT))
    if os.path.exists(dirname) is False:
        os.makedirs(dirname)


def check_exist_workdir():
    work_dir = os.path.abspath(GlobalConfig.WORK_DIR)
    if os.path.exists(work_dir) is False:
        os.makedirs(work_dir)
    if os.path.isdir(work_dir) is False:
        logger.error("work path is not a dir, path is %s", work_dir)
        sys.exit(0)


def check_exist_rpm():
    rpm_path = os.path.abspath(GlobalConfig.RPMS)
    if os.path.exists(rpm_path) is False:
        os.makedirs(rpm_path)
    if os.path.isdir(rpm_path) is False:
        logger.error("rpms path exists, but not a dir! path is %s", GlobalConfig.RPMS)
        sys.exit(0)


def check_exist_iso():
    if os.path.exists(os.path.abspath(GlobalConfig.ISO)) is False:
        logger.error("can not found the iso file, path is %s", GlobalConfig.ISO)
        sys.exit(0)


def get_edreplace_parser(parser):
    GlobalConfig.ISO = parser.iso[0]
    if parser.rpms is not None and len(parser.rpms) > 0:
        GlobalConfig.RPMS = parser.rpms[0]
    if parser.work_dir is not None and len(parser.work_dir) > 0:
        GlobalConfig.WORK_DIR = parser.work_dir[0]
    if parser.tmpl is not None and len(parser.tmpl) > 0:
        GlobalConfig.TMPL = parser.tmpl[0]
    GlobalConfig.OUTPUT = parser.output[0]
    if parser.replace_dir is not None and len(parser.replace_dir) > 0:
        GlobalConfig.REPLACE_DIR = parser.replace_dir[0]

    check_exist_iso()
    check_exist_rpm()
    check_exist_workdir()
    check_exist_outdir()
    check_exist_tmpfile()


def get_ediso_parser(parser):
    GlobalConfig.ISO = parser.iso[0]
    GlobalConfig.RPMS = parser.rpms[0]
    GlobalConfig.WORK_DIR = parser.work_dir[0]
    GlobalConfig.PRODUCT_NAME = parser.product_name[0]
    GlobalConfig.VERSION_ID = parser.version_id[0]
    GlobalConfig.VERSION_INFO = parser.version_info[0]
    GlobalConfig.OUTPUT = parser.output[0]
    check_exist_iso()
    check_exist_rpm()
    check_exist_workdir()
    check_exist_outdir()


def get_edvendor_parser(parser):
    GlobalConfig.VENDOR_SRC = parser.vendor_src[0]
    GlobalConfig.PRODUCT_NAME = parser.product_name[0]
    GlobalConfig.VERSION_INFO = parser.version_info[0]
    GlobalConfig.VERSION_ID = parser.version_id[0]
    GlobalConfig.LOGOS = parser.logos[0]
    GlobalConfig.RPM_OUTPUT = parser.output[0]


def process_with_vendor(parser):
    """
    更换软件包中的发行商信息
    :param parser:
    :return:NA
    """
    init_config(parser)
    vendor_processor = ReplaceVendor()
    build_processor = RPMBuild()
    helper_list = get_all_pkg()
    for helper in helper_list:
        vendor_processor.add_replace_pkg(helper)
        build_processor.add_build_pkg(helper)
    vendor_processor.do_replace()
    build_processor.do_rpmbuild()
    runcmd.cp_output_rpm(GlobalConfig.RPM_OUTPUT)


def process_with_iso(parser):
    """
    根据发行商软件包重新生成ISO
    :param parser:
    :return:
    """
    init_config(parser)
    iso_rebuilder = RebuildISO(GlobalConfig.ISO,
                               GlobalConfig.RPMS,
                               GlobalConfig.WORK_DIR,
                               GlobalConfig.OUTPUT,
                               GlobalConfig.PRODUCT_NAME,
                               GlobalConfig.VERSION_ID,
                               GlobalConfig.VERSION_INFO)
    iso_rebuilder.do_iso_rebuild()


def process_with_replace_rpm(parser):
    """
    根据传入的ISO和软件包来替换ISO中软件包/小系统软件包，重做ISO
    :param parser:
    :return:
    """
    init_config(parser)
    iso_rebuilder = RebuildISOWithPackage(GlobalConfig.ISO,
                                          GlobalConfig.RPMS,
                                          GlobalConfig.WORK_DIR,
                                          GlobalConfig.OUTPUT,
                                          GlobalConfig.ARCH,
                                          GlobalConfig.REPLACE_DIR,
                                          GlobalConfig.TMPL)
    iso_rebuilder.check_dependence()
    iso_rebuilder.check_diskfree()
    iso_rebuilder.do_iso_rebuild()


def parse_cli():
    parser = argparse.ArgumentParser(description="rebuild RPM/ISO for linux distribution")

    subparser = parser.add_subparsers(dest="sub_cmd")
    # 重新编译软件包
    parse_edvendor(subparser)
    # 重建ISO
    parse_ediso(subparser)
    # 替换rpm并重建ISO
    parse_edreplace(subparser)

    config = parser.parse_args()

    if config.sub_cmd is None:
        parser.print_help()
        sys.exit(0)
    else:
        return config


def parse_edreplace(subparser):
    edreplace_parser = subparser.add_parser("edreplace", help="rebebuild iso with new package")
    edreplace_parser.add_argument("--iso", required=True, nargs=1,
                                  dest="iso",
                                  help="iso file used to rebuild")
    edreplace_parser.add_argument("--rpms", required=False, nargs=1,
                                  dest="rpms",
                                  help="path for all rpms which are used to rebuild iso")
    edreplace_parser.add_argument("--work-dir", required=False, nargs=1,
                                  dest="work_dir",
                                  help="dir for iso rebuild, it must has enough space "
                                       "to uncompress the whole iso file")
    edreplace_parser.add_argument("--tmpl", required=False, nargs=1,
                                  dest="tmpl",
                                  help="the tmpl file of build iso with replace package")
    edreplace_parser.add_argument("--output", required=True, nargs=1,
                                  dest="output",
                                  help="dir for rebuild iso, it must has enough space "
                                       "to store the whole iso file")
    edreplace_parser.add_argument("--replace-dir", required=False, nargs=1,
                                  dest="replace_dir",
                                  help="dir for replace files")
    edreplace_parser.set_defaults(func=process_with_replace_rpm)


def parse_ediso(subparser):
    ediso_parser = subparser.add_parser("ediso", help="rebuild iso")
    ediso_parser.add_argument("--iso", required=True, nargs=1,
                              dest="iso",
                              help="iso file used to rebuild")
    ediso_parser.add_argument("--rpms", required=True, nargs=1,
                              dest="rpms",
                              help="path for all rpms which are used to rebuild iso")
    ediso_parser.add_argument("--work-dir", required=True, nargs=1,
                              dest="work_dir",
                              help="dir for iso rebuild, it must has enough space "
                                   "to uncompress the whole iso file")
    ediso_parser.add_argument("--output", required=True, nargs=1,
                              dest="output",
                              help="dir for rebuild iso, it must has enough space "
                                   "to store the whole iso file")
    ediso_parser.add_argument("--product-name", required=True, nargs=1,
                              dest="product_name",
                              help="new product name")
    ediso_parser.add_argument("--version-info", required=True, nargs=1,
                              dest="version_info",
                              help="new version")
    ediso_parser.add_argument("--version-id", required=True, nargs=1,
                              dest="version_id",
                              help="new version id, it may be equal to version info")
    ediso_parser.set_defaults(func=process_with_iso)


def parse_edvendor(subparser):
    edvendor_parser = subparser.add_parser("edvendor",
                                           help="rebuild rpms for vendor info")
    edvendor_parser.add_argument("--vendor-src", required=True, nargs=1,
                                 dest="vendor_src",
                                 help="src path for all vendor rpms")
    edvendor_parser.add_argument("--product-name", required=True, nargs=1,
                                 dest="product_name",
                                 help="new product name")
    edvendor_parser.add_argument("--version-info", required=True, nargs=1,
                                 dest="version_info",
                                 help="new version")
    edvendor_parser.add_argument("--version-id", required=True, nargs=1,
                                 dest="version_id",
                                 help="new version id, it may be equal to version info")
    edvendor_parser.add_argument("--logos", required=True, nargs=1,
                                 dest="logos",
                                 help="path for logos resources")
    edvendor_parser.add_argument("--output", required=True, nargs=1,
                                 dest="output",
                                 help="dir for output rebuild rpm")
    edvendor_parser.set_defaults(func=process_with_vendor)


def clean_work_dir():
    if os.path.exists(GlobalConfig.WORK_DIR):
        shutil.rmtree(GlobalConfig.WORK_DIR)


def main():
    parser = parse_cli()
    parser.func(parser)
    clean_work_dir()


if __name__ == "__main__":
    main()
